package agents;

import java.util.ArrayList;

import javax.annotation.Resource;
import javax.jms.ConnectionFactory;
import javax.jms.Topic;

import model.ACLMessage;
import model.AgentInfo;
import model.AgentType;
import model.Host;
import util.QuicksortProposals;
import util.TenderTimer;

/**
 * Session Bean implementation class MasterAgent
 */

public class MasterAgent extends Agent {
	
	protected ArrayList<ACLMessage> proposals=new ArrayList<ACLMessage>();
	
	protected ACLMessage ClientMessage;
	
	protected boolean acceptingProposals;
	
	protected String tenderStatus;

	private TenderTimer tenderTimeLimit;

	@Resource(mappedName = "java:/ConnectionFactory")
	private ConnectionFactory connectionFactory;
    
    @Resource(mappedName = "java:/topic/mojTopic2")
    private Topic topic;
	
	
    public MasterAgent() {
		super();
		// TODO Auto-generated constructor stub
		agentInfo.setAgentType(AgentType.MASTER);
		acceptingProposals = false;
		tenderStatus = "";
	}

	/**
     * @see Agent#Agent(Host)
     */
    public MasterAgent(Host localHost) {
        super(localHost);
        this.agentInfo=new AgentInfo(localHost,AgentType.MASTER);
        this.acceptingProposals = false;
        this.tenderStatus = "";
    }
       
    /**
     * @see Agent#Agent(AgentInfo)
     */
    
    public MasterAgent(AgentInfo agentInfo) {
        super(agentInfo);
        // TODO Auto-generated constructor stub
    }

    
	@Override
	public void processMessage(ACLMessage message) {
		// TODO Auto-generated method stub
		super.processMessage(message);
		if(message==null || message.getProtocol()==null)
			return;
		if(message.getSender().getAgentType().equals(AgentType.MERCHANT) && message.getProtocol().equals("call for proposal")){
			
			ClientMessage = message;
			sendMessage(createCallForProposal(message));
			
			acceptingProposals = true;
			
			//proposalTimer();
			tenderTimeLimit=new TenderTimer(this);
			tenderTimeLimit.start();
			
		}else if(message.getProtocol().equals("refuse")) return;
			
		else if(message.getProtocol().equals("propose")) {
			
			if(acceptingProposals){
				System.out.println("****************MASTER AGENT GOT PROPOSAL:"+message.getSender()+": "+message.getContent());
				proposals.add(message);
			}
			
		}else if(message.getProtocol().equals("failure")){
			
			if(proposals.size() == 0){
				tenderStatus = "failed";
				sendMessage(createTenderDone(ClientMessage));
				ClientMessage = null;
				return;
			}
			
			sendMessage(createAcceptProposal(proposals.get(0)));
			proposals.remove(0);
			sortProposals();
			
		}else if(message.getProtocol().equals("inform done")){
			
			sendMessage(createTenderDone(ClientMessage));
			ClientMessage = null;
			
			for(int cnt = 0; cnt < proposals.size(); cnt++)
				sendMessage(createRejectProposal(proposals.get(cnt)));
			
			proposals.clear();
			
		}
	}
	
	protected ACLMessage createCallForProposal(ACLMessage message){
		return new ACLMessage(getAgentInfo(), null,"call for proposal", message.getContent());
	}
	
	protected ACLMessage createRejectProposal(ACLMessage message){
		
		return new ACLMessage(getAgentInfo(), message.getSender(),"proposal rejected", "proposal rejected");
	}
	
	protected ACLMessage createAcceptProposal(ACLMessage message){
		
		return new ACLMessage(getAgentInfo(), message.getSender(), "proposal accepted","proposal accepted");
	}
	
	protected ACLMessage createTenderDone(ACLMessage message){
		
		//return new ACLMessage(getAgentInfo(),null,"Tender is done."+tenderStatus);
		return new ACLMessage(getAgentInfo(), ClientMessage.getSender(), "tender done", tenderStatus);
	}
	
	protected void sortProposals(){
		QuicksortProposals.quicksort(proposals);
	}
	
	public void proposalTimer(int timerLength){
		
		if(timerLength<=0)
			timerLength=5000;
		try {
			
			Thread.sleep(timerLength);
			proposalTimerExpired();
			
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
	
	protected synchronized void proposalTimerExpired() {
		
		acceptingProposals = false;
		
		if(proposals.size() == 0){
			tenderStatus = "failed";
			sendMessage(createTenderDone(ClientMessage));
			ClientMessage = null;
			return;
		}
		
		sortProposals();
		
		tenderStatus = "success: " + proposals.get(0).getContent();
		sendMessage(createAcceptProposal(proposals.get(0)));
		proposals.remove(0);
	}
}
